﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;

using LengthAiCalculate;

namespace NxERP.Bll
{
    /// <summary>
    /// 成品最优锯切计算
    /// </summary>
    public partial class LengthAiCalculate
    {
        private readonly int CutNum = 8;
        private readonly List<string> jg = new List<string>();
        private readonly string JhOrderby = "num desc";
        private readonly string ScOrderBy = "num desc";

        /// <summary>
        /// 订单
        /// </summary>
		private DataTable jh = null;

        /// <summary>
        /// 原料
        /// </summary>
		private DataTable sc = null;

        /// <summary>
        /// 订单表备份
        /// </summary>
        private readonly DataTable jhcopy = null;

        /// <summary>
        /// 原来表备份
        /// </summary>
        private readonly DataTable sccopy = null;

        private readonly double AllJhNum = 0;
        private readonly DataTable CutGroupTable = null;
        private readonly int radixpoint = 2;
        private readonly int planDifficultyValue = 0;
        private readonly int noPlanDifficultyValue = 0;
        private readonly double maxLength = 18;
        private readonly double minLength = 6;
        private readonly int cutNum = 8;
        private readonly double lengthStep = 1;
        private Dictionary<double, ResultTable> resultTable = new Dictionary<double, ResultTable>();

        /// <summary>
        /// 成品锯切优化计算
        /// </summary>
        /// <param name="calculationConfig">初始化配置参数</param>
        public LengthAiCalculate(CalculationConfig calculationConfig)
        {
            jh = calculationConfig.JhDataTable;
            sc = calculationConfig.ScDataTable;
            jhcopy = calculationConfig.JhDataTable.Copy();
            sccopy = calculationConfig.ScDataTable.Copy();
            noPlanDifficultyValue = calculationConfig.NoPlanDifficultyValue;
            planDifficultyValue = calculationConfig.PlanDifficultyValue;
            cutNum = calculationConfig.CutNum;
            lengthStep = calculationConfig.LengthStep;
            if (calculationConfig.MaxLength <= 18 && calculationConfig.MaxLength >= 6)
            {
                maxLength = calculationConfig.MaxLength;
            }
            if (calculationConfig.MinLength <= 18 && calculationConfig.MinLength >= 6)
            {
                minLength = calculationConfig.MinLength;
            }
            if (calculationConfig.RadixPoint > 2 && calculationConfig.RadixPoint <= 8) { radixpoint = calculationConfig.RadixPoint; }
            foreach (DataRow jhrow in jhcopy.Rows)
            {
                AllJhNum += int.Parse(jhrow["num"].ToString());
            }
            if (calculationConfig.CutNum > 0) { CutNum = calculationConfig.CutNum; }
            if (calculationConfig.JhOrderBy != null) { JhOrderby = calculationConfig.JhOrderBy; }
            if (calculationConfig.ScOrderBy != null) { ScOrderBy = calculationConfig.ScOrderBy; }
            if (CutGroupTable == null)
            {
                CutGroupTable = new DataTable("cutgrouptable");
                CutGroupTable.Columns.Add(new DataColumn
                {
                    DataType = Type.GetType("System.Int32"),
                    ColumnName = "isfree"
                });
                CutGroupTable.Columns.Add(new DataColumn
                {
                    DataType = Type.GetType("System.Double"),
                    ColumnName = "lg"
                });
                CutGroupTable.Columns.Add(new DataColumn
                {
                    DataType = Type.GetType("System.Int32"),
                    ColumnName = "num"
                });
                CutGroupTable.Columns.Add(new DataColumn
                {
                    DataType = Type.GetType("System.String"),
                    ColumnName = "group"
                });
            }
        }

        /// <summary>
        /// 计算结果列表
        /// </summary>
        /// <param name="scDt">计算后剩余的成品列表</param>
        /// <param name="jhDt">计算剩余的订单计划列表</param>
        /// <returns>计算结果列表,格式：大料支数*大料长度=短料长度1*短料长度1支数+...</returns>
        public AiResult GetResult()
        {
            AiResult aiResult = new AiResult
            {
                ScSurplus = sc,
                JhSurplus = jh,
                CutGroupList = jg,
                AchievePercent = 0,
                NoAchievePercent = 0,
                AchieveAllCount = 0,
                NoAchieveAllCount = 0
            };
            Dictionary<double, int> js = new Dictionary<double, int>();
            Dictionary<double, int> scxh = new Dictionary<double, int>();
            CutGroupTable.Rows.Clear();
            int DifficultyValue = 0;
            foreach (var item in jg)
            {
                int dlnum = int.Parse(item.Split('_')[1].Split('=')[0].Split('*')[0]);
                double dllength = double.Parse(item.Split('_')[1].Split('=')[0].Split('*')[1]);
                DifficultyValue += item.Split('=')[1].Split('+').Length;
                DataRow dr = CutGroupTable.NewRow();
                dr["isfree"] = item.Substring(0, 1);
                dr["lg"] = dllength;
                dr["num"] = dlnum;
                dr["group"] = item.Split('=')[1];
                CutGroupTable.Rows.Add(dr);
                if (scxh.ContainsKey(dllength))
                {
                    scxh[dllength] = scxh[dllength] + dlnum;
                }
                else
                {
                    scxh.Add(dllength, dlnum);
                }
                string[] zh = item.Split('_')[1].Split('=')[1].Split('+');
                foreach (var item1 in zh)
                {
                    double length = double.Parse(item1.Split('*')[0]);
                    int num = int.Parse(item1.Split('*')[1]) * dlnum;
                    if (js.ContainsKey(length))
                    {
                        js[length] = js[length] + num;
                    }
                    else
                    {
                        js.Add(length, num);
                    }
                }
            }
            DataTable _jh = jhcopy;
            if (!_jh.Columns.Contains("oknum"))
            {
                _jh.Columns.Add(new DataColumn
                {
                    DataType = Type.GetType("System.Double"),
                    ColumnName = "oknum",
                    DefaultValue = "0"
                });
            }
            if (!_jh.Columns.Contains("okpercent"))
            {
                _jh.Columns.Add(new DataColumn
                {
                    DataType = Type.GetType("System.Double"),
                    ColumnName = "okpercent",
                    DefaultValue = "0"
                });
            }
            if (!_jh.Columns.Contains("nopercent"))
            {
                _jh.Columns.Add(new DataColumn
                {
                    DataType = Type.GetType("System.Double"),
                    ColumnName = "nopercent",
                    DefaultValue = "0"
                });
            }
            double nonum = 0;
            double oknum = 0;
            foreach (DataRow item in _jh.Rows)
            {
                double _lg = double.Parse(item["lg"].ToString());
                double num = int.Parse(item["num"].ToString());
                if (js.ContainsKey(_lg))
                {
                    item["oknum"] = js[_lg];
                    if (js[_lg] > num)
                    {
                        nonum += nonum + js[_lg] - num;
                        item["nopercent"] = Math.Round((((js[_lg] - num) / num) * 100), radixpoint);
                        item["okpercent"] = 100;
                        oknum += num;
                    }
                    else
                    {
                        item["okpercent"] = Math.Round((js[_lg] / num * 100), radixpoint);
                        oknum += js[_lg];
                    }
                }
            }
            DataTable _sc = sccopy;
            if (!_sc.Columns.Contains("usenum"))
            {
                _sc.Columns.Add(new DataColumn
                {
                    DataType = Type.GetType("System.Int32"),
                    ColumnName = "usenum",
                    DefaultValue = "0"
                });
            }
            if (!_sc.Columns.Contains("lastnum"))
            {
                _sc.Columns.Add(new DataColumn
                {
                    DataType = Type.GetType("System.Int32"),
                    ColumnName = "lastnum",
                    DefaultValue = "0"
                });
            }
            foreach (DataRow item in _sc.Rows)
            {
                double _lg = double.Parse(item["lg"].ToString());
                double num = int.Parse(item["num"].ToString());
                if (scxh.ContainsKey(_lg))
                {
                    item["usenum"] = scxh[_lg];
                    item["lastnum"] = num - scxh[_lg];
                }
                else
                {
                    item["usenum"] = 0;
                    item["lastnum"] = num;
                }
            }
            aiResult.NoAchievePercent = Math.Round(nonum / AllJhNum * 100, radixpoint);
            aiResult.AchievePercent = Math.Round(oknum / AllJhNum * 100, radixpoint);
            DifficultyValue += (int)aiResult.NoAchievePercent * noPlanDifficultyValue;
            DifficultyValue += Math.Abs((int)(100 - aiResult.AchievePercent)) * planDifficultyValue;
            aiResult.NoAchieveAllCount = nonum;
            aiResult.AchieveAllCount = AllJhNum;
            aiResult.PlanDoneTable = _jh;
            aiResult.MaterialUseTable = _sc;
            aiResult.CutGroupTable = CutGroupTable;
            aiResult.DifficultyValue = DifficultyValue;
            return aiResult;
        }

        /// <summary>
        /// 获取计算结果
        /// </summary>
        /// <param name="jg">                   </param>
        /// <param name="ScSurplus">            </param>
        /// <param name="JhSurplus">            </param>
        /// <param name="jhCopy">               </param>
        /// <param name="scCopy">               </param>
        /// <param name="radixpoint">           </param>
        /// <param name="noPlanDifficultyValue"></param>
        /// <param name="planDifficultyValue">  </param>
        /// <returns></returns>
        public static AiResult GetResult(List<string> jg, DataTable ScSurplus, DataTable JhSurplus, DataTable jhCopy, DataTable scCopy, int radixpoint, int noPlanDifficultyValue, int planDifficultyValue)
        {
            int allJhNum = 0;
            foreach (DataRow jhrow in jhCopy.Rows)
            {
                allJhNum += int.Parse(jhrow["num"].ToString());
            }
            DataTable CutGroupTable = new DataTable("cutgrouptable");
            CutGroupTable.Columns.Add(new DataColumn
            {
                DataType = Type.GetType("System.Int32"),
                ColumnName = "isfree"
            });
            CutGroupTable.Columns.Add(new DataColumn
            {
                DataType = Type.GetType("System.Double"),
                ColumnName = "lg"
            });
            CutGroupTable.Columns.Add(new DataColumn
            {
                DataType = Type.GetType("System.Int32"),
                ColumnName = "num"
            });
            CutGroupTable.Columns.Add(new DataColumn
            {
                DataType = Type.GetType("System.String"),
                ColumnName = "group"
            });

            AiResult aiResult = new AiResult
            {
                ScSurplus = ScSurplus,
                JhSurplus = JhSurplus,
                CutGroupList = jg,
                AchievePercent = 0,
                NoAchievePercent = 0,
                AchieveAllCount = 0,
                NoAchieveAllCount = 0
            };
            Dictionary<double, int> js = new Dictionary<double, int>();
            Dictionary<double, int> scxh = new Dictionary<double, int>();
            CutGroupTable.Rows.Clear();
            int DifficultyValue = 0;
            foreach (var item in jg)
            {
                int dlnum = int.Parse(item.Split('_')[1].Split('=')[0].Split('*')[0]);
                double dllength = double.Parse(item.Split('_')[1].Split('=')[0].Split('*')[1]);
                DifficultyValue += item.Split('=')[1].Split('+').Length;
                DataRow dr = CutGroupTable.NewRow();
                dr["isfree"] = item.Substring(0, 1);
                dr["lg"] = dllength;
                dr["num"] = dlnum;
                dr["group"] = item.Split('=')[1];
                CutGroupTable.Rows.Add(dr);
                if (scxh.ContainsKey(dllength))
                {
                    scxh[dllength] = scxh[dllength] + dlnum;
                }
                else
                {
                    scxh.Add(dllength, dlnum);
                }
                string[] zh = item.Split('_')[1].Split('=')[1].Split('+');
                foreach (var item1 in zh)
                {
                    double length = double.Parse(item1.Split('*')[0]);
                    int num = int.Parse(item1.Split('*')[1]) * dlnum;
                    if (js.ContainsKey(length))
                    {
                        js[length] = js[length] + num;
                    }
                    else
                    {
                        js.Add(length, num);
                    }
                }
            }
            DataTable _jh = jhCopy.Copy();
            if (!_jh.Columns.Contains("oknum"))
            {
                _jh.Columns.Add(new DataColumn
                {
                    DataType = Type.GetType("System.Double"),
                    ColumnName = "oknum",
                    DefaultValue = "0"
                });
            }
            if (!_jh.Columns.Contains("okpercent"))
            {
                _jh.Columns.Add(new DataColumn
                {
                    DataType = Type.GetType("System.Double"),
                    ColumnName = "okpercent",
                    DefaultValue = "0"
                });
            }
            if (!_jh.Columns.Contains("nopercent"))
            {
                _jh.Columns.Add(new DataColumn
                {
                    DataType = Type.GetType("System.Double"),
                    ColumnName = "nopercent",
                    DefaultValue = "0"
                });
            }
            double nonum = 0;
            double oknum = 0;
            foreach (DataRow item in _jh.Rows)
            {
                double _lg = double.Parse(item["lg"].ToString());
                double num = int.Parse(item["num"].ToString());
                if (js.ContainsKey(_lg))
                {
                    item["oknum"] = js[_lg];
                    if (js[_lg] > num)
                    {
                        nonum += nonum + js[_lg] - num;
                        item["nopercent"] = Math.Round((((js[_lg] - num) / num) * 100), radixpoint);
                        item["okpercent"] = 100;
                        oknum += num;
                    }
                    else
                    {
                        item["okpercent"] = Math.Round((js[_lg] / num * 100), radixpoint);
                        oknum += js[_lg];
                    }
                }
            }
            DataTable _sc = scCopy.Copy();
            if (!_sc.Columns.Contains("usenum"))
            {
                _sc.Columns.Add(new DataColumn
                {
                    DataType = Type.GetType("System.Int32"),
                    ColumnName = "usenum",
                    DefaultValue = "0"
                });
            }
            if (!_sc.Columns.Contains("lastnum"))
            {
                _sc.Columns.Add(new DataColumn
                {
                    DataType = Type.GetType("System.Int32"),
                    ColumnName = "lastnum",
                    DefaultValue = "0"
                });
            }
            foreach (DataRow item in _sc.Rows)
            {
                double _lg = double.Parse(item["lg"].ToString());
                double num = int.Parse(item["num"].ToString());
                if (scxh.ContainsKey(_lg))
                {
                    item["usenum"] = scxh[_lg];
                    item["lastnum"] = num - scxh[_lg];
                }
                else
                {
                    item["usenum"] = 0;
                    item["lastnum"] = num;
                }
            }
            aiResult.NoAchievePercent = Math.Round(nonum / allJhNum * 100, radixpoint);
            aiResult.AchievePercent = Math.Round(oknum / allJhNum * 100, radixpoint);
            DifficultyValue += (int)aiResult.NoAchievePercent * noPlanDifficultyValue;
            DifficultyValue += Math.Abs((int)(100 - aiResult.AchievePercent)) * planDifficultyValue;
            aiResult.NoAchieveAllCount = nonum;
            aiResult.AchieveAllCount = allJhNum;
            aiResult.PlanDoneTable = _jh;
            aiResult.MaterialUseTable = _sc;
            aiResult.CutGroupTable = CutGroupTable;
            aiResult.DifficultyValue = DifficultyValue;
            return aiResult;
        }

        /// <summary>
        /// 1种定尺
        /// </summary>
        /// <returns>计算结果</returns>
        public AiResult OneLength()
        {
            OneLengthCut();
            return GetResult();
        }

        /// <summary>
        /// 2种定尺
        /// </summary>
        /// <returns>计算结果</returns>
        public AiResult TwoLength()
        {
            TwoLengthCut();
            return GetResult();
        }

        /// <summary>
        /// 3种定尺
        /// </summary>
        /// <returns>计算结果</returns>
        public AiResult ThreeLength()
        {
            ThreeLengthCut();
            return GetResult();
        }

        /// <summary>
        /// 1种定尺、2种定尺、3种定尺顺序计算
        /// </summary>
        /// <param name="isFreedom">是否计算非计划,true计算，false不计算</param>
        /// <returns>计算结果</returns>
        public AiResult CalculationModule_1_2_3(BoolConfig boolConfig)
        {
            TwoLengthCut();
            OneLengthCut();
            ThreeLengthCut();
            Freedom(boolConfig);
            return GetResult();
        }

        /// <summary>
        /// 1种定尺、3种定尺、2种定尺顺序计算
        /// </summary>
        /// <param name="isFreedom">是否计算非计划,true计算，false不计算</param>
        /// <returns></returns>
        public AiResult CalculationModule_1_3_2(BoolConfig boolConfig)
        {
            OneLengthCut();
            ThreeLengthCut();
            TwoLengthCut();
            Freedom(boolConfig);
            return GetResult();
        }

        /// <summary>
        /// 2种定尺、1种定尺、3种定尺顺序计算
        /// </summary>
        /// <param name="isFreedom">是否计算非计划,true计算，false不计算</param>
        /// <returns></returns>
        public AiResult CalculationModule_2_1_3(BoolConfig boolConfig)
        {
            TwoLengthCut();
            OneLengthCut();
            ThreeLengthCut();
            Freedom(boolConfig);
            return GetResult();
        }

        /// <summary>
        /// 2种定尺、3种定尺、1种定尺顺序计算
        /// </summary>
        /// <param name="isFreedom">是否计算非计划,true计算，false不计算</param>
        /// <returns></returns>

        public AiResult CalculationModule_2_3_1(BoolConfig boolConfig)
        {
            TwoLengthCut();
            ThreeLengthCut();
            OneLengthCut();
            Freedom(boolConfig);
            return GetResult();
        }

        /// <summary>
        /// 3种定尺、1种定尺、2种定尺顺序计算
        /// </summary>
        /// <param name="isFreedom">是否计算非计划,true计算，false不计算</param>
        /// <returns></returns>

        public AiResult CalculationModule_3_1_2(BoolConfig boolConfig)
        {
            ThreeLengthCut();
            OneLengthCut();
            TwoLengthCut();
            Freedom(boolConfig);
            return GetResult();
        }

        /// <summary>
        /// 3种定尺、2种定尺、1种定尺顺序计算
        /// </summary>
        /// <param name="isFreedom">是否计算非计划,true计算，false不计算</param>
        /// <returns></returns>

        public AiResult CalculationModule_3_2_1(BoolConfig boolConfig)
        {
            ThreeLengthCut();
            TwoLengthCut();
            OneLengthCut();
            Freedom(boolConfig);
            return GetResult();
        }

        /// <summary>
        /// 1种定尺、2种定尺顺序计算
        /// </summary>
        /// <param name="isFreedom">是否计算非计划,true计算，false不计算</param>
        /// <returns></returns>
        public AiResult CalculationModule_1_2(BoolConfig boolConfig)
        {
            OneLengthCut();
            TwoLengthCut();
            Freedom(boolConfig);
            return GetResult();
        }

        /// <summary>
        /// 1种定尺、3种定尺顺序计算
        /// </summary>
        /// <param name="isFreedom">是否计算非计划,true计算，false不计算</param>
        /// <returns></returns>
        public AiResult CalculationModule_1_3(BoolConfig boolConfig)
        {
            OneLengthCut();
            ThreeLengthCut();
            Freedom(boolConfig);
            return GetResult();
        }

        /// <summary>
        /// 2种定尺、1种定尺顺序计算
        /// </summary>
        /// <param name="isFreedom">是否计算非计划,true计算，false不计算</param>
        /// <returns></returns>
        public AiResult CalculationModule_2_1(BoolConfig boolConfig)
        {
            TwoLengthCut();
            OneLengthCut();
            Freedom(boolConfig);
            return GetResult();
        }

        /// <summary>
        /// 2种定尺、3种定尺顺序计算
        /// </summary>
        /// <param name="isFreedom">是否计算非计划,true计算，false不计算</param>
        /// <returns></returns>
        public AiResult CalculationModule_2_3(BoolConfig boolConfig)
        {
            TwoLengthCut();
            ThreeLengthCut();
            Freedom(boolConfig);
            return GetResult();
        }

        /// <summary>
        /// 3种定尺、1种定尺顺序计算
        /// </summary>
        /// <param name="isFreedom">是否计算非计划,true计算，false不计算</param>
        /// <returns></returns>
        public AiResult CalculationModule_3_1(BoolConfig boolConfig)
        {
            ThreeLengthCut();
            OneLengthCut();
            Freedom(boolConfig);
            return GetResult();
        }

        /// <summary>
        /// 3种定尺、2种定尺顺序计算
        /// </summary>
        /// <param name="isFreedom">是否计算非计划,true计算，false不计算</param>
        /// <returns></returns>
        public AiResult CalculationModule_3_2(BoolConfig boolConfig)
        {
            ThreeLengthCut();
            TwoLengthCut();
            Freedom(boolConfig);
            return GetResult();
        }

        public AiResult CalculationModule_1_2_F(BoolConfig boolConfig)
        {
            OneLengthCut();
            TwoLength();
            Freedom(boolConfig);
            return GetResult();
        }

        /// <summary>
        /// 单定尺计算
        /// </summary>
        private void OneLengthCut()
        {
            DataRow[] jhtemp = null;
            if (jh != null)
            {
                jhtemp = jh.Select("num>0", JhOrderby);
            }
            DataRow[] sctemp = null;
            if (sc != null)
            {
                sctemp = sc.Select("num>0", ScOrderBy);
            }

            if (jhtemp == null || sctemp == null)
            {
                return;
            }
            foreach (DataRow row1 in sctemp)
            {
                double sclg = double.Parse(row1["lg"].ToString());
                foreach (DataRow jhrow1 in jhtemp)
                {
                    int scnum = int.Parse(row1["num"].ToString());
                    if (scnum <= 0) break;
                    double jhlg = double.Parse(jhrow1["lg"].ToString());
                    int jhnum = int.Parse(jhrow1["num"].ToString());
                    double sy = sclg % jhlg;
                    int zz = (int)(sclg / jhlg);
                    if (zz > cutNum) continue;
                    int xh_scnum = jhnum / zz;
                    if (xh_scnum > scnum) { xh_scnum = scnum; }
                    if (xh_scnum == 0) { xh_scnum = 1; }
                    if (sy == 0)
                    {
                        row1["num"] = scnum - xh_scnum;
                        jhrow1["num"] = jhnum - xh_scnum * zz;
                        if (xh_scnum > 0)
                        {
                            jg.Add("0_" + xh_scnum.ToString() + "*" + sclg.ToString() + "=" + jhlg.ToString() + "*" + zz.ToString());
                            if (jhtemp.CopyToDataTable().Select("num>0", JhOrderby).Length > 0)
                            {
                                jh = jhtemp.CopyToDataTable().Select("num>0", JhOrderby).CopyToDataTable();
                            }
                            else
                            {
                                jh = null;
                            }
                            if (sctemp.CopyToDataTable().Select("num>0", ScOrderBy).Length > 0)
                            {
                                sc = sctemp.CopyToDataTable().Select("num>0", ScOrderBy).CopyToDataTable();
                            }
                            else
                            {
                                sc = null;
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 两种定尺计算
        /// </summary>
        private void TwoLengthCut()
        {
            DataRow[] jhtemp = null;
            if (jh != null)
            {
                jhtemp = jh.Select("num>0", JhOrderby);
            }
            DataRow[] sctemp = null;
            if (sc != null)
            {
                sctemp = sc.Select("num>0", ScOrderBy);
            }

            if (jhtemp == null || sctemp == null)
            {
                return;
            }
            foreach (DataRow row1 in sctemp)
            {
                double sclg = double.Parse(row1["lg"].ToString());
                foreach (DataRow jhrow1 in jhtemp)
                {
                    double jhlg1 = double.Parse(jhrow1["lg"].ToString());
                    for (int L1 = 1; L1 <= CutNum - 1; L1++)
                    {
                        int jhnum1 = int.Parse(jhrow1["num"].ToString());
                        double lgsum = 0;
                        if (jhnum1 <= 0) continue;
                        for (int L2 = 1; L2 <= CutNum - L1; L2++)
                        {
                            foreach (DataRow jhrow2 in jhtemp)
                            {
                                int scnum = int.Parse(row1["num"].ToString());
                                if (scnum <= 0) break;
                                double jhlg2 = double.Parse(jhrow2["lg"].ToString());
                                int jhnum2 = int.Parse(jhrow2["num"].ToString());
                                if (jhlg1 == jhlg2) continue;
                                if (jhnum2 <= 0) continue;
                                lgsum = L1 * jhlg1 + L2 * jhlg2;
                                if (lgsum == sclg)
                                {
                                    int[] _xh = { 0, 0 };
                                    _xh[0] = (int)jhnum1 / L1;
                                    _xh[1] = (int)jhnum2 / L2;
                                    double xh = GetArrayMinNum(_xh); ;
                                    if (xh > scnum) xh = scnum;
                                    jhrow2["num"] = int.Parse(jhrow2["num"].ToString()) - L2 * xh;
                                    jhrow1["num"] = int.Parse(jhrow1["num"].ToString()) - L1 * xh;
                                    row1["num"] = scnum - xh;
                                    if (xh > 0)
                                    {
                                        jg.Add("0_" + xh.ToString() + "*" + sclg.ToString() + "=" + jhlg1.ToString() + "*" + L1.ToString() + "+" + jhlg2.ToString() + "*" + L2.ToString());

                                        if (jhtemp.CopyToDataTable().Select("num>0", JhOrderby).Length > 0)
                                        {
                                            jh = jhtemp.CopyToDataTable().Select("num>0", JhOrderby).CopyToDataTable();
                                        }
                                        else
                                        {
                                            jh = null;
                                        }
                                        if (sctemp.CopyToDataTable().Select("num>0", ScOrderBy).Length > 0)
                                        {
                                            sc = sctemp.CopyToDataTable().Select("num>0", ScOrderBy).CopyToDataTable();
                                        }
                                        else
                                        {
                                            sc = null;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 三种尺寸计算
        /// </summary>
        private void ThreeLengthCut()
        {
            DataRow[] jhtemp = null;
            if (jh != null)
            {
                jhtemp = jh.Select("num>0", JhOrderby);
            }
            DataRow[] sctemp = null;
            if (sc != null)
            {
                sctemp = sc.Select("num>0", ScOrderBy);
            }

            if (jhtemp == null || sctemp == null)
            {
                return;
            }
            foreach (DataRow row1 in sctemp)
            {
                double sclg = double.Parse(row1["lg"].ToString());
                foreach (DataRow jhrow1 in jhtemp)
                {
                    double jhlg1 = double.Parse(jhrow1["lg"].ToString());
                    for (int L1 = 1; L1 <= CutNum - 2; L1++)
                    {
                        int jhnum1 = int.Parse(jhrow1["num"].ToString());
                        if (jhnum1 <= 0) continue;
                        double lgsum = 0;
                        foreach (DataRow jhrow2 in jhtemp)
                        {
                            double jhlg2 = double.Parse(jhrow2["lg"].ToString());
                            if (jhlg2 == jhlg1) continue;
                            for (int L2 = 1; L2 <= CutNum - 1 - L1; L2++)
                            {
                                int jhnum2 = int.Parse(jhrow2["num"].ToString());
                                if (jhnum2 <= 0 || jhlg1 <= 0) continue;
                                foreach (DataRow jhrow3 in jhtemp)
                                {
                                    int scnum = int.Parse(row1["num"].ToString());
                                    if (scnum <= 0) break;
                                    double jhlg3 = double.Parse(jhrow3["lg"].ToString());
                                    int jhnum3 = int.Parse(jhrow3["num"].ToString());
                                    if (jhlg3 == jhlg1 || jhlg3 == jhlg2) continue;
                                    if (jhnum3 <= 0 || jhnum1 <= 0 || jhnum2 <= 0) continue;
                                    for (int L3 = 1; L3 <= CutNum - L1 - L2; L3++)
                                    {
                                        if (jhlg1 == jhlg2 || jhlg1 == jhlg3 || jhlg2 == jhlg3) { continue; }
                                        lgsum = L1 * jhlg1 + L2 * jhlg2 + L3 * jhlg3;
                                        if (sclg == lgsum)
                                        {
                                            int[] _xh = { 0, 0, 0 };
                                            _xh[0] = (int)jhnum1 / L1;
                                            _xh[1] = (int)jhnum2 / L2;
                                            _xh[2] = (int)jhnum3 / L3;
                                            double xh = GetArrayMinNum(_xh); ;
                                            if (xh > scnum) xh = scnum;
                                            if (xh > 0)
                                            {
                                                jg.Add("0_" + xh.ToString() + "*" + sclg.ToString() + "=" + jhlg1.ToString() + "*" + L1.ToString() + "+" + jhlg2.ToString() + "*" + L2.ToString() + "+" + jhlg3.ToString() + "*" + L3.ToString());
                                                jhrow3["num"] = int.Parse(jhrow3["num"].ToString()) - L3 * xh;
                                                jhrow2["num"] = int.Parse(jhrow2["num"].ToString()) - L2 * xh;
                                                jhrow1["num"] = int.Parse(jhrow1["num"].ToString()) - L1 * xh;
                                                row1["num"] = scnum - xh;
                                                if (jhtemp.CopyToDataTable().Select("num>0", JhOrderby).Length > 0)
                                                {
                                                    jh = jhtemp.CopyToDataTable().Select("num>0", JhOrderby).CopyToDataTable();
                                                }
                                                else
                                                {
                                                    jh = null;
                                                }
                                                if (sctemp.CopyToDataTable().Select("num>0", ScOrderBy).Length > 0)
                                                {
                                                    sc = sctemp.CopyToDataTable().Select("num>0", ScOrderBy).CopyToDataTable();
                                                }
                                                else
                                                {
                                                    sc = null;
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 按照三种尺寸匹配订单，可带非计划支数,结果前缀1_
        /// </summary>
        private void FreedomThreeCount()
        {
            DataRow[] jhtemp = null;
            if (jh != null)
            {
                jhtemp = jh.Select("num>0", JhOrderby);
            }
            DataRow[] sctemp = null;
            if (sc != null)
            {
                sctemp = sc.Select("num>0", ScOrderBy);
            }

            if (jhtemp == null || sctemp == null)
            {
                return;
            }
            foreach (DataRow row1 in sctemp)
            {
                double sclg = double.Parse(row1["lg"].ToString());
                foreach (DataRow jhrow1 in jhtemp)
                {
                    double scnum = int.Parse(row1["num"].ToString());
                    if (scnum <= 0) break;
                    double jhlg1 = double.Parse(jhrow1["lg"].ToString());
                    for (int L1 = 1; L1 <= CutNum - 2; L1++)
                    {
                        double jhnum1 = int.Parse(jhrow1["num"].ToString());
                        double lgsum = 0;
                        foreach (DataRow jhrow2 in jhtemp)
                        {
                            double jhlg2 = double.Parse(jhrow2["lg"].ToString());
                            if (jhlg2 == jhlg1) continue;
                            for (int L2 = 1; L2 <= CutNum - 1 - L1; L2++)
                            {
                                double jhnum2 = int.Parse(jhrow2["num"].ToString());
                                foreach (DataRow jhrow3 in jhtemp)
                                {
                                    double jhlg3 = double.Parse(jhrow3["lg"].ToString());
                                    double jhnum3 = int.Parse(jhrow3["num"].ToString());
                                    if (jhlg3 == jhlg1 || jhlg3 == jhlg2) continue;
                                    if (jhnum3 <= 0 && jhnum1 <= 0 && jhnum2 <= 0) continue;
                                    for (int L3 = 1; L3 <= CutNum - L1 - L2; L3++)
                                    {
                                        if (jhlg1 == jhlg2 || jhlg1 == jhlg3 || jhlg2 == jhlg3) { continue; }
                                        lgsum = L1 * jhlg1 + L2 * jhlg2 + L3 * jhlg3;
                                        if (sclg == lgsum)
                                        {
                                            int[] _xh = { 0, 0, 0 };
                                            _xh[0] = (int)jhnum1 / L1;
                                            _xh[1] = (int)jhnum2 / L2;
                                            _xh[2] = (int)jhnum3 / L3;
                                            double xh = GetArrayMinNum(_xh); ;
                                            if (xh > scnum) xh = scnum;
                                            if (xh > 0)
                                            {
                                                jg.Add("1_" + xh.ToString() + "*" + sclg.ToString() + "=" + jhlg1.ToString() + "*" + L1.ToString() + "+" + jhlg2.ToString() + "*" + L2.ToString() + "+" + jhlg3.ToString() + "*" + L3.ToString());
                                                jhrow3["num"] = int.Parse(jhrow3["num"].ToString()) - L3 * xh;
                                                jhrow2["num"] = int.Parse(jhrow2["num"].ToString()) - L2 * xh;
                                                jhrow1["num"] = int.Parse(jhrow1["num"].ToString()) - L1 * xh;
                                                row1["num"] = scnum - xh;
                                                scnum -= xh;
                                                jhnum1 -= L1 * xh;
                                                jhnum2 -= L2 * xh;
                                                jhnum3 -= L3 * xh;
                                            }
                                            if (jhtemp.CopyToDataTable().Select("num>0", JhOrderby).Length > 0)
                                            {
                                                jh = jhtemp.CopyToDataTable().Select("num>0", JhOrderby).CopyToDataTable();
                                            }
                                            else
                                            {
                                                jh = null;
                                            }
                                            if (sctemp.CopyToDataTable().Select("num>0", ScOrderBy).Length > 0)
                                            {
                                                sc = sctemp.CopyToDataTable().Select("num>0", ScOrderBy).CopyToDataTable();
                                            }
                                            else
                                            {
                                                sc = null;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 按照三种尺寸匹配订单，两种订单长度，一种非计划长度,结果前缀1_
        /// </summary>
        private void FreedowThreeLength()
        {
            DataRow[] jhtemp = null;
            if (jh != null)
            {
                jhtemp = jh.Select("num>0", JhOrderby);
            }
            DataRow[] sctemp = null;
            if (sc != null)
            {
                sctemp = sc.Select("num>0", ScOrderBy);
            }

            if (jhtemp == null || sctemp == null)
            {
                return;
            }
            foreach (DataRow row1 in sctemp)
            {
                double sclg = double.Parse(row1["lg"].ToString());
                foreach (DataRow jhrow1 in jhtemp)
                {
                    double scnum = int.Parse(row1["num"].ToString());
                    if (scnum <= 0) break;
                    double jhlg1 = double.Parse(jhrow1["lg"].ToString());
                    for (int L1 = 1; L1 <= CutNum - 2; L1++)
                    {
                        double jhnum1 = int.Parse(jhrow1["num"].ToString());
                        if (jhnum1 <= 0) continue;
                        double lgsum = 0;
                        foreach (DataRow jhrow2 in jhtemp)
                        {
                            double jhlg2 = double.Parse(jhrow2["lg"].ToString());
                            if (jhlg2 == jhlg1) continue;
                            for (int L2 = 1; L1 <= CutNum - 1 - L1; L1++)
                            {
                                double jhnum2 = int.Parse(jhrow2["num"].ToString());
                                lgsum = L1 * jhlg1 + L2 * jhlg2;
                                if (jhnum2 <= 0) continue;
                                double sylg = sclg - lgsum;
                                if (sylg >= minLength && sylg <= maxLength)
                                {
                                    int[] _xh = { 0, 0 };
                                    _xh[0] = (int)jhnum1 / L1;
                                    _xh[1] = (int)jhnum2 / L2;
                                    double xh = GetArrayMinNum(_xh); ;
                                    if (xh > scnum) xh = scnum;
                                    jg.Add("1_" + xh.ToString() + "*" + sclg.ToString() + "=" + jhlg1.ToString() + "*" + L1.ToString() + "+" + jhlg2.ToString() + "*" + L2.ToString() + "+" + sylg.ToString() + "*1");
                                    jhrow2["num"] = int.Parse(jhrow2["num"].ToString()) - L2 * xh;
                                    jhrow1["num"] = int.Parse(jhrow1["num"].ToString()) - L1 * xh;
                                    row1["num"] = scnum - xh;
                                    scnum -= xh;
                                    jhnum1 -= L1 * xh;
                                    jhnum2 -= L2 * xh;
                                }
                                if (jhtemp.CopyToDataTable().Select("num>0", JhOrderby).Length > 0)
                                {
                                    jh = jhtemp.CopyToDataTable().Select("num>0", JhOrderby).CopyToDataTable();
                                }
                                else
                                {
                                    jh = null;
                                }
                                if (sctemp.CopyToDataTable().Select("num>0", ScOrderBy).Length > 0)
                                {
                                    sc = sctemp.CopyToDataTable().Select("num>0", ScOrderBy).CopyToDataTable();
                                }
                                else
                                {
                                    sc = null;
                                }
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 两种尺寸带自由长度，结果前缀1_
        /// </summary>
        private void FreedowTwoLength()
        {
            DataRow[] jhtemp = null;
            if (jh != null)
            {
                jhtemp = jh.Select("num>0", JhOrderby);
            }
            DataRow[] sctemp = null;
            if (sc != null)
            {
                sctemp = sc.Select("num>0", ScOrderBy);
            }

            if (jhtemp == null || sctemp == null)
            {
                return;
            }
            foreach (DataRow row1 in sctemp)
            {
                double sclg = double.Parse(row1["lg"].ToString());
                int scnum = int.Parse(row1["num"].ToString());
                if (scnum <= 0) continue;
                foreach (DataRow jhrow1 in jhtemp)
                {
                    double jhlg1 = double.Parse(jhrow1["lg"].ToString());
                    for (int L1 = 1; L1 <= CutNum; L1++)
                    {
                        int jhnum1 = int.Parse(jhrow1["num"].ToString());
                        if (jhnum1 <= 0) continue;
                        double lgsum = 0;
                        for (int L2 = 1; L2 <= CutNum - L1; L2++)
                        {
                            for (double lenght = minLength; lenght <= maxLength; lenght += lengthStep)
                            {
                                lgsum = jhlg1 * L1 + L2 * lenght;
                                if (lgsum == sclg)
                                {
                                    int xh = (int)jhnum1 / L1;
                                    if (xh > scnum) xh = scnum;
                                    if (xh > 0)
                                    {
                                        jg.Add("1_" + xh.ToString() + "*" + sclg.ToString() + "=" + jhlg1.ToString() + "*" + L1.ToString() + "+" + lenght.ToString() + "*" + L2.ToString());
                                        jhrow1["num"] = int.Parse(jhrow1["num"].ToString()) - L1 * xh;
                                        row1["num"] = scnum - xh;
                                        scnum -= xh;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 计划必保
        /// </summary>
        private void PlanConfirm()
        {
            DataRow[] jhtemp = null;
            if (jh != null)
            {
                jhtemp = jh.Select("num>0", "num desc");
            }
            DataRow[] sctemp = null;
            if (sc != null)
            {
                sctemp = sc.Select("num>0", ScOrderBy);
            }

            if (jhtemp == null || sctemp == null)
            {
                return;
            }
            foreach (DataRow row1 in sctemp)
            {
                double sclg = double.Parse(row1["lg"].ToString());
                double scnum = int.Parse(row1["num"].ToString());
                foreach (DataRow jhrow1 in jhtemp)
                {
                    if (scnum <= 0) continue;
                    for (int L = CutNum - 1; L >= 1; L--)
                    {
                        double jhlg = double.Parse(jhrow1["lg"].ToString());
                        double jhnum = int.Parse(jhrow1["num"].ToString());
                        if (jhnum <= 0) continue;
                        double sy = sclg - L * jhlg;
                        if (sy < 0) continue;
                        double zz = jhnum / L;
                        double lz = jhnum % L;
                        int xh_scnum = (int)zz;
                        if (lz > 0)
                        {
                            xh_scnum = (int)zz + 1;
                        }
                        if (xh_scnum > scnum) { xh_scnum = (int)scnum; }

                        if (sy == 0)
                        {
                            row1["num"] = scnum - xh_scnum;
                            jhrow1["num"] = jhnum - xh_scnum * L;
                            scnum -= xh_scnum;
                            if (xh_scnum > 0)
                            {
                                jg.Add("2_" + xh_scnum.ToString() + "*" + sclg.ToString() + "=" + jhlg.ToString() + "*" + L.ToString());
                                if (jhtemp.CopyToDataTable().Select("num>0", JhOrderby).Length > 0)
                                {
                                    jh = jhtemp.CopyToDataTable().Select("num>0", JhOrderby).CopyToDataTable();
                                }
                                else
                                {
                                    jh = null;
                                }
                                if (sctemp.CopyToDataTable().Select("num>0", ScOrderBy).Length > 0)
                                {
                                    sc = sctemp.CopyToDataTable().Select("num>0", ScOrderBy).CopyToDataTable();
                                }
                                else
                                {
                                    sc = null;
                                }
                            }
                        }
                        else
                        {
                            if (sy >= minLength && sy <= maxLength)
                            {
                                if (xh_scnum > 0)
                                {
                                    row1["num"] = scnum - xh_scnum;
                                    jhrow1["num"] = jhnum - xh_scnum * L;
                                    scnum -= xh_scnum;
                                    jg.Add("2_" + xh_scnum.ToString() + "*" + sclg.ToString() + "=" + jhlg.ToString() + "*" + L.ToString() + "+" + sy.ToString() + "*1");
                                    if (jhtemp.CopyToDataTable().Select("num>0", JhOrderby).Length > 0)
                                    {
                                        jh = jhtemp.CopyToDataTable().Select("num>0", JhOrderby).CopyToDataTable();
                                    }
                                    else
                                    {
                                        jh = null;
                                    }
                                    if (sctemp.CopyToDataTable().Select("num>0", ScOrderBy).Length > 0)
                                    {
                                        sc = sctemp.CopyToDataTable().Select("num>0", ScOrderBy).CopyToDataTable();
                                    }
                                    else
                                    {
                                        sc = null;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 按照定尺组合匹配（刘永清）
        /// </summary>
        /// <returns></returns>
        public AiResult PatternMatching(SqlHelper sqlHelper)
        {
            DataTable baseCutTable = sqlHelper.GetDataTableFromSql("SELECT [length],[num],cutGroup,cutGuid,mLength,cutLenthItemId FROM [v_LA_CutTable]");
            List<double> mLength = new List<double>();
            DataTable scDt = sc;
            DataTable jhDt = jh;
            foreach (DataRow item in scDt.Rows)
            {
                mLength.Add(double.Parse(item["lg"].ToString()));
            }
            if (scDt == null || scDt.Rows.Count == 0)
            {
            }
            string s1 = "(" + string.Join(",", mLength) + ")";
            Dictionary<double, int> jhCutNum = new Dictionary<double, int>();
            List<double> jhLength = new List<double>();
            foreach (DataRow item in jhDt.Rows)
            {
                jhLength.Add(double.Parse(item["lg"].ToString()));
            }
            List<string> rs = new List<string>();
            foreach (var item in jhLength)
            {
                DataTable cutDt = sqlHelper.GetDataTableFromSql($"SELECT [cutGuid],[cutGroup],[mLength],[num],[length] FROM[v_LA_CutTable] WHERE mLength IN {s1} AND [length] = {item} ORDER BY LEN(cutGroup)-LEN(REPLACE(cutGroup,'+','')) DESC,num DESC,mLength ASC");
                int i = 0;
                foreach (DataRow cutRow in cutDt.Rows)
                {
                    string[] cutGroup = cutRow["cutGroup"].ToString().Split('=')[1].Split('+');
                    bool flag = true;
                    foreach (var c in cutGroup)
                    {
                        string[] l = c.Split('*');
                        if (!jhLength.Contains(double.Parse(l[0])))
                        {
                            flag = false;
                            break;
                        }
                    }
                    if (flag)
                    {
                        i++;
                    }
                }
                jhCutNum.Add(item, i);
            }
            List<KeyValuePair<double, int>> myList = new List<KeyValuePair<double, int>>(jhCutNum);
            myList = myList.OrderBy(p => p.Value).ThenBy(p => p.Key).ToList();
            foreach (var item in myList)
            {
                double s = item.Key;
                DataTable cutDt = sqlHelper.GetDataTableFromSql($"SELECT [cutGuid],[cutGroup],[mLength],[num],[length] FROM[v_LA_CutTable] WHERE mLength IN {s1} AND [length] = {item.Key} ORDER BY LEN(cutGroup)-LEN(REPLACE(cutGroup,'+','')) DESC,num DESC,mLength ASC");
                DataTable reusltDt = cutDt.Clone();
                foreach (DataRow cutRow in cutDt.Rows)
                {
                    string[] cutGroup = cutRow["cutGroup"].ToString().Split('=')[1].Split('+');
                    bool flag = true;
                    foreach (var c in cutGroup)
                    {
                        string[] l = c.Split('*');
                        if (!jhLength.Contains(double.Parse(l[0])))
                        {
                            flag = false;
                            break;
                        }
                    }
                    if (flag)
                    {
                        reusltDt.ImportRow(cutRow);
                    }
                }
                foreach (DataRow row in reusltDt.Rows)
                {
                    string l = row["length"].ToString();
                    string guid = row["cutGuid"].ToString();
                    DataRow[] mainLength = baseCutTable.Select($"cutGuid='{guid}' AND length={l}");
                    DataRow[] noMainLength = baseCutTable.Select($"cutGuid='{guid}' AND length<>{l}");
                    int mainNum = int.Parse(mainLength[0]["num"].ToString());
                    string cut = mainLength[0]["cutGroup"].ToString();
                    int noMainNum = 0;
                    string L = mainLength[0]["mLength"].ToString();
                    DataRow[] scRow = scDt.Select($"lg={L} AND num>0");
                    if (scRow.Length == 0)
                    {
                        continue;
                    }
                    int scNum = int.Parse(scRow[0]["num"].ToString());
                    if (noMainLength.Length > 0)
                    {
                        noMainNum = int.Parse(noMainLength[0]["num"].ToString());
                        DataRow[] jhRow = jhDt.Select($"lg='{row["length"]}' AND num>0");
                        DataRow[] nojhRow = jhDt.Select($"lg='{noMainLength[0]["length"]}' AND num>0");
                        int jhNum = 0;
                        int nojhnum = 0;
                        if (jhRow.Length > 0)
                        {
                            jhNum = int.Parse(jhRow[0]["num"].ToString());
                        }
                        if (nojhRow.Length > 0)
                        {
                            nojhnum = int.Parse(nojhRow[0]["num"].ToString());
                        }
                        int realNum = 0;
                        if (jhNum / mainNum >= nojhnum / noMainNum)
                        {
                            realNum = nojhnum / noMainNum;
                        }
                        else
                        {
                            realNum = jhNum / mainNum;
                        }
                        if (realNum > 0)
                        {
                            if (scNum <= realNum)
                            {
                                realNum = scNum;
                            }

                            if (jhRow.Length > 0)
                            {
                                jhRow[0]["num"] = jhNum - mainNum * realNum;
                            }
                            if (nojhRow.Length > 0)
                            {
                                nojhRow[0]["num"] = nojhnum - noMainNum * realNum;
                            }
                            scRow[0]["num"] = scNum - realNum;
                            scNum -= realNum;
                            rs.Add("0_" + realNum.ToString() + "*" + cut);
                        }
                    }
                    else
                    {
                        DataRow[] jhRow = jhDt.Select($"lg='{l}' AND num>0");
                        int jhNum = 0;
                        if (jhRow.Length > 0)
                        {
                            jhNum = int.Parse(jhRow[0]["num"].ToString());
                            int realNum = 0;
                            realNum = jhNum / mainNum;
                            if (realNum > 0)
                            {
                                if (scNum <= realNum)
                                {
                                    realNum = scNum;
                                }
                                jhRow[0]["num"] = jhNum - mainNum * realNum;
                                scRow[0]["num"] = scNum - realNum;
                                scNum -= scNum - realNum;
                                rs.Add("0_" + realNum.ToString() + "*" + cut);
                            }
                        }
                    }
                }
            }
            jh = jhDt;
            sc = scDt;
            OneLengthCut();
            TwoLengthCut();
            ThreeLengthCut();
            FreedowTwoLength();
            FreedomThreeCount();
            FreedowThreeLength();
            PlanConfirm();
            LastCut();
            rs.AddRange(jg);
            //rs.AddRange(jg);
            return GetResult(rs, sc, jh, jhcopy, sccopy, radixpoint, noPlanDifficultyValue, planDifficultyValue);
        }

        /// <summary>
        /// 剩余坯料生产
        /// </summary>
        public void LastCut()
        {
            DataRow[] sctemp = null;
            if (sc != null)
            {
                sctemp = sc.Select("num>0", ScOrderBy);
            }

            if (sctemp == null)
            {
                return;
            }
            foreach (DataRow row1 in sctemp)
            {
                double sclg = double.Parse(row1["lg"].ToString());
                int scnum = int.Parse(row1["num"].ToString());
                if (scnum <= 0) break;
                for (int L1 = 1; L1 < CutNum - 1; L1++)
                {
                    double jhlg = sclg / L1;
                    int sy = (int)(sclg % L1);
                    if (jhlg >= minLength && jhlg <= maxLength)
                    {
                        if (sy == 0)
                        {
                            jg.Add("3_" + scnum.ToString() + "*" + sclg.ToString() + "=" + jhlg.ToString() + "*" + L1.ToString());
                            row1["num"] = 0;
                            scnum = 0;
                            if (sctemp.CopyToDataTable().Select("num>0", ScOrderBy).Length > 0)
                            {
                                sc = sctemp.CopyToDataTable().Select("num>0", ScOrderBy).CopyToDataTable();
                            }
                            else
                            {
                                sc = null;
                            }
                            break;
                        }
                    }
                }
            }
        }

        public (List<string> jg, DataTable sc) LastCut(DataTable sc)
        {
            DataRow[] sctemp = null;
            if (sc != null)
            {
                sctemp = sc.Select("num>0", ScOrderBy);
            }

            if (sctemp == null)
            {
                return (null, sc);
            }
            List<string> jg = new List<string>();
            foreach (DataRow row1 in sctemp)
            {
                double sclg = double.Parse(row1["lg"].ToString());
                int scnum = int.Parse(row1["num"].ToString());
                if (scnum <= 0) break;
                for (int L1 = 1; L1 <= CutNum; L1++)
                {
                    double jhlg = sclg / L1;
                    int sy = (int)(sclg % L1);
                    if (sy == 0)
                    {
                        row1["num"] = 0;
                        scnum = 0;
                        jg.Add("3_" + scnum.ToString() + "*" + sclg.ToString() + "=" + jhlg.ToString() + "*" + L1.ToString());
                        if (sctemp.CopyToDataTable().Select("num>0", ScOrderBy).Length > 0)
                        {
                            sc = sctemp.CopyToDataTable().Select("num>0", ScOrderBy).CopyToDataTable();
                        }
                        else
                        {
                            sc = null;
                        }
                        break;
                    }
                }
            }
            return (jg, sc);
        }

        /// <summary>
        /// 自由量计算
        /// </summary>
        /// <param name="boolConfig"></param>
        private void Freedom(BoolConfig boolConfig)
        {
            if (boolConfig.IsFreedomCount) { FreedomThreeCount(); }
            if (boolConfig.IsFreedomLength)
            {
                FreedowTwoLength();
                FreedowThreeLength();
            }
            PlanConfirm();
            LastCut();
        }

        private int GetArrayMinNum(int[] ar)
        {
            int rt = 1;
            if (ar != null && ar.Length > 0)
            {
                Array.Sort(ar);
                foreach (var item in ar)
                {
                    if (item > 0)
                    {
                        rt = item;
                        break;
                    }
                }
            }
            return rt;
        }
    }

    /// <summary>
    /// 计算结果对象
    /// </summary>
    public class AiResult
    {
        /// <summary>
        /// 锯切组合结果列表(List形式)
        /// </summary>
        public List<string> CutGroupList;

        /// <summary>
        /// 锯切组合结果表(DataTable形式)
        /// </summary>
        public DataTable CutGroupTable;

        /// <summary>
        /// 计划明细完成对比表
        /// </summary>
        public DataTable PlanDoneTable;

        /// <summary>
        /// 原料使用情况对比表
        /// </summary>
        public DataTable MaterialUseTable;

        /// <summary>
        /// 大料剩余表
        /// </summary>
        public DataTable ScSurplus;

        /// <summary>
        /// 计划剩余表
        /// </summary>
        public DataTable JhSurplus;

        /// <summary>
        /// 计划完成率
        /// </summary>
        public double AchievePercent;

        /// <summary>
        /// 非计划率
        /// </summary>
        public double NoAchievePercent;

        /// <summary>
        /// 计划总支数
        /// </summary>
        public double AchieveAllCount;

        /// <summary>
        /// 非计划支数
        /// </summary>
        public double NoAchieveAllCount;

        /// <summary>
        /// 计划难度
        /// </summary>
        public int DifficultyValue;
    }

    /// <summary>
    /// 计算配置对象
    /// </summary>
    public class CalculationConfig
    {
        /// <summary>
        /// 订单计划表
        /// </summary>
        public DataTable JhDataTable;

        /// <summary>
        /// 大料计划表
        /// </summary>
        public DataTable ScDataTable;

        /// <summary>
        /// 最大分段数量
        /// </summary>
        public int CutNum;

        /// <summary>
        /// 计划优顺序
        /// </summary>
        public string JhOrderBy;

        /// <summary>
        /// 原料优先顺序
        /// </summary>
        public string ScOrderBy;

        /// <summary>
        /// 百分百小数位数
        /// </summary>
        public int RadixPoint;

        /// <summary>
        /// 一个难度值对应非计划率点数
        /// </summary>
        public int NoPlanDifficultyValue;

        /// <summary>
        /// 一个难度值对应计划未完成率点数
        /// </summary>
        public int PlanDifficultyValue;

        /// <summary>
        /// 非计划最小长度
        /// </summary>
        public double MinLength;

        /// <summary>
        /// 非计划最大长度
        /// </summary>
        public double MaxLength;

        /// <summary>
        /// 编组支数
        /// </summary>
        public int GroupNum { get; set; } = 1;

        /// <summary>
        /// 尺寸间距
        /// </summary>
        public double LengthStep { get; set; }
    }

    /// <summary>
    /// 配置项
    /// </summary>
    public class BoolConfig
    {
        /// <summary>
        /// 是否带支数自由量
        /// </summary>
        public bool IsFreedomCount;

        /// <summary>
        /// 是否带长度自由量
        /// </summary>
        public bool IsFreedomLength;

        /// <summary>
        /// 是否要求计划必保
        /// </summary>
        public bool IsPlanConfirm;
    }
}